using System;

namespace Behaviorize
{
	public class ArrangementStep : Step
	{
		internal ArrangementStep(ScenarioVersion containingScenarioVersion, MulticastDelegate action) : base(containingScenarioVersion, action){}
		internal ArrangementStep(ScenarioVersion containingScenarioVersion, MulticastDelegate action, object arg1) : base(containingScenarioVersion, action, arg1) { }
		internal ArrangementStep(ScenarioVersion containingScenarioVersion, MulticastDelegate action, object arg1, object arg2) : base(containingScenarioVersion, action, arg1, arg2) { }
		internal ArrangementStep(ScenarioVersion containingScenarioVersion, MulticastDelegate action, object arg1, object arg2, object arg3) : base(containingScenarioVersion, action, arg1, arg2, arg3) { }
		internal ArrangementStep(ScenarioVersion containingScenarioVersion, MulticastDelegate action, object arg1, object arg2, object arg3, object arg4) : base(containingScenarioVersion, action, arg1, arg2, arg3, arg4) { }

		public ArrangementStep And(Action precondition)
		{
			var step = new ArrangementStep(ScenarioVersion, precondition);
			ScenarioVersion.ArrangementSteps.Add(step);
			return step;
		}

		public ArrangementStep And<T1>(Action<T1> action, T1 arg1)
		{
			var step = new ArrangementStep(ScenarioVersion, action, arg1);
			ScenarioVersion.ArrangementSteps.Add(step);
			return step;
		}

		public ArrangementStep And<T1, T2>(Action<T1, T2> action, T1 arg1, T2 arg2)
		{
			var step = new ArrangementStep(ScenarioVersion, action, arg1, arg2);
			ScenarioVersion.ArrangementSteps.Add(step);
			return step;
		}

		public ArrangementStep And<T1, T2, T3>(Action<T1, T2, T3> action, T1 arg1, T2 arg2, T3 arg3)
		{
			var step = new ArrangementStep(ScenarioVersion, action, arg1, arg2, arg3);
			ScenarioVersion.ArrangementSteps.Add(step);
			return step;
		}

		public ArrangementStep And<T1, T2, T3, T4>(Action<T1, T2, T3, T4> action, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
		{
			var step = new ArrangementStep(ScenarioVersion, action, arg1, arg2, arg3, arg4);
			ScenarioVersion.ArrangementSteps.Add(step);
			return step;
		}

		public ActionStep When(Action action)
		{
			var step = new ActionStep(ScenarioVersion, action);
			ScenarioVersion.ActionSteps.Add(step);
			return step;
		}

		public ActionStep When<T1>(Action<T1> action, T1 arg1)
		{
			var step = new ActionStep(ScenarioVersion, action, arg1);
			ScenarioVersion.ActionSteps.Add(step);
			return step;
		}

		public ActionStep When<T1, T2>(Action<T1, T2> action, T1 arg1, T2 arg2)
		{
			var step = new ActionStep(ScenarioVersion, action, arg1, arg2);
			ScenarioVersion.ActionSteps.Add(step);
			return step;
		}

		public ActionStep When<T1, T2, T3>(Action<T1, T2, T3> action, T1 arg1, T2 arg2, T3 arg3)
		{
			var step = new ActionStep(ScenarioVersion, action, arg1, arg2, arg3);
			ScenarioVersion.ActionSteps.Add(step);
			return step;
		}

		public ActionStep When<T1, T2, T3, T4>(Action<T1, T2, T3, T4> action, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
		{
			var step = new ActionStep(ScenarioVersion, action, arg1, arg2, arg3, arg4);
			ScenarioVersion.ActionSteps.Add(step);
			return step;
		}

		internal override string ClauseName
		{
			get { return "Given"; }
		}
	}
}